/**
 * Copyright © 2016-2021 The Thingsboard Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.thingsboard.rule.engine.tb;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.gson.JsonParser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.thingsboard.rule.engine.api.*;
import org.thingsboard.rule.engine.api.sms.SmsSender;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
import org.thingsboard.server.common.data.kv.KvEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.data.sms.config.SmsProviderConfiguration;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.session.SessionMsgType;
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
import org.thingsboard.server.dao.util.mapping.JacksonUtil;
import org.thingsboard.server.remote.upload.gateway.GatewayService;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.thingsboard.common.util.DonAsynchron.withCallback;
import static org.thingsboard.server.common.data.DataConstants.CONNECT_EVENT;
import static org.thingsboard.server.common.data.DataConstants.DISCONNECT_EVENT;
import static org.thingsboard.server.common.msg.session.SessionMsgType.POST_ATTRIBUTES_REQUEST;
import static org.thingsboard.server.common.msg.session.SessionMsgType.POST_TELEMETRY_REQUEST;

@Slf4j
@RuleNode(
        type = ComponentType.EXTERNAL,
        name = "thingsboard iot hub",
        configClazz = RemoteTbNodeConfiguration.class,
        nodeDescription = "Publish messages to the Remote Thingsboard IoT Hub.",
        nodeDetails = "Will publish message payload to the Remote Thingsboard IoT Hub",
        uiResources = {"static/rulenode/rulenode-core-config.js"}
       // configDirective = "tbActionNodeSendSmsConfig",
      //  icon = "sms"
)
public class RemoteTbNode implements TbNode {

    private RemoteTbNodeConfiguration remoteTbNodeConfiguration;
    @Override
    public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {

    }

    @Override
    public void onMsg(TbContext ctx, TbMsg msg) {
      // log.warn("消息类型 [{}]-[{}]-[{}]",msg.getType(),msg.getMetaData(),msg.getData());
        GatewayService service= ctx.getGatewayService();
        if(!service.isUsable()){
            ctx.tellFailure(msg,new Throwable("远程连接未开启"));
            return;
        }
        if (msg.getType().equals(CONNECT_EVENT)) {
            service.onDeviceConnect(getName(msg.getMetaData()),getType(msg.getMetaData()));
        }else  if (msg.getType().equals(DISCONNECT_EVENT)) {
            service.onDeviceDisconnect(getName(msg.getMetaData()));
        }else  if (msg.getType().equals(POST_ATTRIBUTES_REQUEST.name())) {
            String src = msg.getData();
            Set<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(new JsonParser().parse(src));
            service.onDeviceAttributesUpdate(getName(msg.getMetaData()),new ArrayList<>(attributes));
        }else  if (msg.getType().equals(POST_TELEMETRY_REQUEST.name())) {
            Map<Long, List<KvEntry>> tsKvMap = JsonConverter.convertToTelemetry(new JsonParser().parse(msg.getData()), getTs(msg));
            if (tsKvMap.isEmpty()) {
                ctx.tellFailure(msg, new IllegalArgumentException("Msg body is empty: " + msg.getData()));
                return;
            }
            List<TsKvEntry> tsKvEntryList = new ArrayList<>();
            for (Map.Entry<Long, List<KvEntry>> tsKvEntry : tsKvMap.entrySet()) {
                for (KvEntry kvEntry : tsKvEntry.getValue()) {
                    tsKvEntryList.add(new BasicTsKvEntry(tsKvEntry.getKey(), kvEntry));
                }
            }
            service.onDeviceTelemetry(getName(msg.getMetaData()),tsKvEntryList );
        }
        ctx.tellSuccess(msg);
    }

    private String getType(TbMsgMetaData metaData) {
        String type=metaData.getValue("deviceType");

        return StringUtils.isEmpty(type)?"default":type;
    }

    private String getName(TbMsgMetaData metaData) {
        String name=metaData.getValue("deviceName");

        return StringUtils.isEmpty(name)?"default":name;
    }


    @Override
    public void destroy() {

    }
    public static long getTs(TbMsg msg) {
        long ts = -1;
        String tsStr = msg.getMetaData().getValue("ts");
        if (!org.springframework.util.StringUtils.isEmpty(tsStr)) {
            try {
                ts = Long.parseLong(tsStr);
            } catch (NumberFormatException e) {
            }
        } else {
            ts = msg.getTs();
        }
        return ts;
    }


}
